﻿// subconsole.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <array>
#include <algorithm>
#include <memory>
#include <cstdlib>
#include <clocale>
#include <cstring>
#include <thread>
#include <mutex>
#include <functional>

#include <process.h>

#include "..\function\base\poly.h"

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers

#include <Windows.h>

#define PRINT_FUNCTION_NAME do {\
  std::wstring wname;\
wprintf_s(L"函数名字：%ls\n", utf82wide(wname, __FUNCTION__).c_str());\
wname.clear();\
wprintf_s(L"函数名字：%ls\n", utf82wide(wname, __func__).c_str());\
wname.clear();\
wprintf_s(L"Decorated 修饰名字：%ls\n", utf82wide(wname, __FUNCDNAME__).c_str());\
wname.clear();\
wprintf_s(L"函数签名：%ls\n", utf82wide(wname, __FUNCSIG__).c_str());\
wname.clear();\
wprintf_s(L"编译日期和时间：%ls", utf82wide(wname, __DATE__).c_str());\
wname.clear();\
wprintf_s(L" %ls\n\n", utf82wide(wname, __TIME__).c_str());\
} while (0)

static std::wstring &utf82wide(std::wstring &wide_name, const char *utf8_name)
{
  int required_size{ 0 };
  size_t length{ strnlen_s(utf8_name, _MAX_PATH) };

  // length 返回的长度里没有空字符 '\0'，所以导致下面这行代码返回的结果里不含空字符
  required_size = MultiByteToWideChar(CP_UTF8, 0LU, utf8_name, static_cast<int>(length), nullptr, 0);
  
  if (required_size <= 0)
    return wide_name;

  wide_name.resize(static_cast<size_t>(required_size));

  MultiByteToWideChar(CP_UTF8, 0LU, utf8_name, static_cast<int>(length), wide_name.data(), static_cast<int>(wide_name.size()));
  return wide_name;
}

#define DUMPEXPR(x) do {\
  wprintf_s(L"%hs = %.*lg\n", #x, DBL_DIG, x);\
}while(0)

int wmain(int argc, wchar_t *argv[], wchar_t *env[])
{
  _wsetlocale(LC_ALL, L"");
  std::ios_base::sync_with_stdio(true);
  Poly poly;
  double *vararr{ nullptr };
  // 测试用函数表达式，函数是一个字符串形式的多项式
  //char str[] = "x1+x2+x3*x5/x4-sin(z4)-100+cos(x3)-x5+100.0-.4-50.123456-pow(x1, x2)";
  //char str[] = "x1+x2+x3*x5/x4-100-x5+100.0-.4-50.123456-pow(x1, x2)";
  //char str[] = "1+2+3*4/5-100.000-4.00000";//+100.000-0.400000-50.1235-pow(1.00000,2.00000)";
  //char str[] = "(((((((((((1+1)))))))))))(((((((((((((((2+1))))))))))))))";
  //char str[] = " \"                ";
  //char str[] = "x1-x2";
  //char str[] = "81 - pow(3, 4)";

  // 1.定义一下函数表达式
  wchar_t str[] = L"sin(3.141592)";

  // 2.设置函数表达式
  if (argc == 1)
    poly.set_poly(str, wcsnlen_s(str, 128));
  else
    poly.set_poly(argv[1], wcsnlen_s(argv[1], 128));

  // 3.如果表达式中有变量，设置变量的值
  if (poly.nvars() > 0) {
    vararr = new double[poly.nvars()];
    for (int i = 0; i < poly.nvars(); i++)
      vararr[i] = double(i + 1);
    poly.set_vars(vararr, poly.nvars());
  }
  // 4.显示函数表达式的详细信息
  std::wcout << poly.dump().c_str();
  // 5.计算
  std::wcout << L"result = " << poly.calc() << std::endl << L"sin(3.141592) = " << sin(3.141592) << std::endl;
  DUMPEXPR(sin(3.141592));
  if (poly.nvars() > 0)
    delete[] vararr;

  return EXIT_SUCCESS;
}

// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu

// Tips for Getting Started: 
//   1. Use the Solution Explorer window to add/manage files
//   2. Use the Team Explorer window to connect to source control
//   3. Use the Output window to see build output and other messages
//   4. Use the Error List window to view errors
//   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
//   6. In the future, to open this project again, go to File > Open > Project and select the .sln file
